// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Collections.ObjectModel; using System.Diagnostics.Contracts; using System.Linq; using System.Xml.Serialization; namespace LargoCommon.Music { /// Real harmonic state. /// Harmonic state represents relations in one real harmonic cluster /// and enable to Compute its characteristics (continuity, impulse,..). [Serializable] [XmlRoot] public sealed class HarmonicStateReal : HarmonicTransfer { #region Fields /// List of tones. private readonly MusicalToneCollection toneList; #endregion #region Constructors /// Initializes a new instance of the HarmonicStateReal class. Serializable. public HarmonicStateReal() { } /// Initializes a new instance of the HarmonicStateReal class. /// Harmonic system. /// List of melodic tones. public HarmonicStateReal(HarmonicSystem harmonicSystem, MusicalToneCollection toneArray) : base(harmonicSystem) { Contract.Requires(harmonicSystem != null); Contract.Requires(toneArray != null); //// if (toneArray == null) { return; } this.toneList = toneArray; if (this.toneList.Count > 1) { byte idx = 0; //// string tmpStr = string.Empty; foreach (var mt in this.ToneList) { mt.ToneIndex = idx++; //// tmpStr += MusicalTone.GetNoteName(mt.Pitch.Element) + mt.Pitch.Octave; } //// HarmonicStateReal.LocalTemporaryProtocol += tmpStr + "\r\n"; this.AddAllIntervals(); } this.SetRealProperties(); } /// Initializes a new instance of the HarmonicStateReal class. /// Harmonic system. /// List of melodic tones. /// Melodic tone. public HarmonicStateReal(HarmonicSystem harmonicSystem, MusicalToneCollection toneArray, MusicalTone givenTone) : base(harmonicSystem) { Contract.Requires(harmonicSystem != null); Contract.Requires(givenTone != null); Contract.Requires(toneArray != null); //// if (toneArray == null) { return; } this.toneList = toneArray; if (this.toneList.Count > 1) { byte idx = 0; foreach (var mt in this.ToneList) { mt.ToneIndex = idx++; } } this.AddIntervalsLeadingToTone(givenTone); this.SetRealProperties(); } /// /// Initializes a new instance of the HarmonicStateReal class. /// /// The given system. public HarmonicStateReal(HarmonicSystem givenSystem) : base(givenSystem) { Contract.Requires(givenSystem != null); } #endregion #region Properties //// Leads to out of memory exception //// public static Dictionary UsedStates = new Dictionary(); /// Gets the property. /// Property description. public float RealContinuity { get; private set; } /// Gets the property. /// Property description. public float RealImpulse { get; private set; } /// Gets the property. /// Property description. public float RealPotential { get; private set; } /// Gets the property. /// Property description. public float RealConsonance { get; private set; } /// Gets list of tones. /// Property description. [XmlIgnore] public MusicalToneCollection ToneList { get { Contract.Ensures(Contract.Result() != null); if (this.toneList == null) { throw new InvalidOperationException("List of tones is null."); } return this.toneList; } } #endregion #region Public static methods /// Returns root values of elements in the structure. /// Harmonic cluster. /// Returns value. public static Collection RootValues(HarmonicCluster harmonicCluster) { Contract.Requires(harmonicCluster != null); //// if (harmonicCluster == null) { return null; } var hS = harmonicCluster.HarmonicSystem; var values = new Collection(); foreach (var rcontinuity in from mt in harmonicCluster.ToneList where mt != null let mts = harmonicCluster.ToneList select new HarmonicStateReal(hS, mts, mt) into state select state.MeanValueOfProperty(GenProperty.RealContinuity, false, true)) { values.Add(rcontinuity); } return values; } /// Returns principal values of elements in the structure. /// Harmonic cluster. /// Returns value. public static Collection PrincipalValues(HarmonicCluster harmonicCluster) { Contract.Requires(harmonicCluster != null); //// if (harmonicCluster == null) { return null; } var hS = harmonicCluster.HarmonicSystem; var values = new Collection(); foreach (var rcontinuity in from mt in harmonicCluster.ToneList where mt != null let mts = harmonicCluster.ToneList select new HarmonicStateReal(hS, mts, mt) into state select state.MeanValueOfProperty(GenProperty.RealContinuity, true, true)) { values.Add(rcontinuity); } return values; } #endregion #region Public methods /// Adds to the given array real intervals to given tone. /// Melodic tone. public void AddIntervalsLeadingToTone(MusicalTone toTone) { Contract.Requires(toTone != null); //// if (toTone == null) { return; } //// const bool ignoreLongIntervals = true; //// this.HarmonicSystem.GetRealInterval(fromTone.Pitch.SystemAltitude, toTone.Pitch.IntervalFrom(fromTone.Pitch)); //// if (toTone.Pitch == null) { return; } var harmonicSystem = this.HarmonicSystem; int toneIndex = toTone.ToneIndex; //// 2011/11 - interval with two equal tones ignored var toneAltitude = toTone.Pitch.SystemAltitude; foreach (var interval in from fromTone in this.ToneList where fromTone != null && fromTone.ToneIndex != toneIndex && fromTone.Pitch != null && fromTone.Pitch.SystemAltitude != toneAltitude select new MusicalInterval(harmonicSystem, fromTone, toTone)) { this.Intervals.Add(interval); } } /// Sets harmonic properties of the cluster. public void SetRealProperties() { switch (this.Intervals.Count) { case 0: return; case 1: this.SetRealPropertiesOfSingleTone(); return; } // float Level = (float)(Math.Sqrt(1+8*intervals.Count)+1)/2; var rcontinuity = this.MeanValueOfProperty(GenProperty.RealContinuity, true, true); var rimpulse = this.MeanValueOfProperty(GenProperty.RealImpulse, true, true); var rsonance = HarmonicSystem.Consonance(rcontinuity, rimpulse); this.RealContinuity = rcontinuity; this.RealImpulse = rimpulse; this.RealPotential = 0f; this.RealConsonance = rsonance; } /// Sets harmonic properties of the cluster. public void SetRealPropertiesOfSingleTone() { this.RealContinuity = 0f; this.RealImpulse = 0f; this.RealPotential = 0f; this.RealConsonance = 0f; } #endregion #region Private methods /// Makes array of intervals between tones of the cluster. private void AddAllIntervals() { foreach (var mt in this.ToneList.Where(mt => mt?.Pitch != null)) { this.AddIntervalsLeadingToTone(mt); } } #endregion } }